package com.wisdytech.ccdserver.bucket.serveice.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wisdytech.ccdserver.bucket.dao.IBucketRecordDao;
import com.wisdytech.ccdserver.bucket.dto.BucketRecordDto;
import com.wisdytech.ccdserver.bucket.dto.BucketTaskDto;
import com.wisdytech.ccdserver.bucket.dto.MinitorBucketViewDto;
import com.wisdytech.ccdserver.bucket.model.Bucket;
import com.wisdytech.ccdserver.bucket.model.BucketRecord;
import com.wisdytech.ccdserver.bucket.serveice.IBucketRecordService;
import com.wisdytech.ccdserver.common.contants.CommonConstants;
import com.wisdytech.ccdserver.common.thread.OurPoolExecutor;
import com.wisdytech.ccdserver.common.utils.HttpUtils;
import com.wisdytech.common.bean.Filter;
import com.wisdytech.common.bean.UniqueResultResponse;
import com.wisdytech.common.utils.SnowFlake;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.rpc.RpcContext;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

/**
 * @author SV00216491
 * @description: TODO
 * @date 2024-04-03 12:29:07
 * @version: 1.0
 */
@Slf4j
public class BucketRecordServiceImpl extends ServiceImpl<IBucketRecordDao, BucketRecord> implements IBucketRecordService {

    @Resource
    private SnowFlake snowFlake;

    @Resource
    private BucketServiceImpl bucketService;

    @Resource
    private BucketTaskServiceImpl bucketTaskService;

    @Autowired
    private HttpUtils httpUtils;

    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;

    // ccd导入查询
    @Override
    public UniqueResultResponse downLoadbatchSaveBucketRecord(List<BucketRecord> bucketRecordList, Filter filter) {
        String taskid = snowFlake.nextStringId();
        String username = RpcContext.getServiceContext().getAttachment("username");
        for (BucketRecord bucketRecord : bucketRecordList) {
            //时间格式转化
            String originMtimeBegin = DateUtil.format(DateUtil.parse(bucketRecord.getOriginMtimeBegin()), "yyyy-MM-dd HH:mm:ss");
            String originMtimeEnd = DateUtil.format(DateUtil.parse(bucketRecord.getOriginMtimeEnd()), "yyyy-MM-dd HH:mm:ss");
            bucketRecord.setOriginMtimeBegin(originMtimeBegin);
            bucketRecord.setOriginMtimeEnd(originMtimeEnd);
            bucketRecord.setCreateUser(username);
            bucketRecord.setDelFlag(CommonConstants.DEL_FALSE);
            bucketRecord.setCreateDate(new Date());
            bucketRecord.setTaskId(taskid);
            bucketRecord.setSearchFlag(CommonConstants.DEL_FALSE);
        }

        //1、保存任务明细
        bucketTaskService.saveBucketTask(filter, taskid);
        //1、根据任务去处理详细的信息
        boolean result = this.saveBatch(bucketRecordList);
        //保存的动作异步处理
        DealSyncBucketRecordDetails(taskid);
//        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
//                    DealSyncBucketRecordDetails(taskid);
//                }
//                , taskExecutor);
////        future.join();
        return UniqueResultResponse.success(result);
    }

    //
    @Override
    public UniqueResultResponse batchSaveBucketRecord(List<BucketRecord> bucketRecordList, String taskid) {
        String username = RpcContext.getServiceContext().getAttachment("username");
        for (BucketRecord bucketRecord : bucketRecordList) {
            //时间格式转化
            String originMtimeBegin = DateUtil.format(DateUtil.parse(bucketRecord.getOriginMtimeBegin()), "yyyy-MM-dd HH:mm:ss");
            String originMtimeEnd = DateUtil.format(DateUtil.parse(bucketRecord.getOriginMtimeEnd()), "yyyy-MM-dd HH:mm:ss");
            bucketRecord.setOriginMtimeBegin(originMtimeBegin);
            bucketRecord.setOriginMtimeEnd(originMtimeEnd);
            bucketRecord.setCreateUser(username);
            bucketRecord.setDelFlag(CommonConstants.DEL_FALSE);
            bucketRecord.setCreateDate(new Date());
            bucketRecord.setTaskId(taskid);
            bucketRecord.setId(snowFlake.nextStringId());
            bucketRecord.setSearchFlag("0");
        }
        boolean result = this.saveBatch(bucketRecordList);
        //保存的动作异步处理
        DealSyncBucketRecordDetails(taskid);

        return UniqueResultResponse.success(result);
    }

    @Override
    public void SavePushRecords(Filter filter) {
        Map<String, Object> queryParams = filter.getQueryMap();
        //前端的条件
        String equipmentCode = (String) queryParams.get("equipmentCode");
        String originMtimeBegin = (String) queryParams.get("originMtimeBegin");
        String originMtimeEnd = (String) queryParams.get("originMtimeEnd");
        BucketRecord bucketRecord = new BucketRecord();
        bucketRecord.setBucket(equipmentCode);
        bucketRecord.setCreateDate(DateUtil.date());
        bucketRecord.setOriginMtimeBegin(originMtimeBegin);
        bucketRecord.setOriginMtimeEnd(originMtimeEnd);
        bucketRecord.setTaskId(null);// TODO

        String username = RpcContext.getServiceContext().getAttachment("username");
        bucketRecord.setCreateDate(new Date());
        bucketRecord.setCreateUser(username);
        this.save(bucketRecord);
    }

    @Override
    public List<BucketTaskDto> searchBucketRecordByTaskid(List<BucketTaskDto> list) {
        for (BucketTaskDto bucketTaskDto : list) {
            LambdaQueryWrapper<BucketRecord> queryWrapper = new LambdaQueryWrapper();
            String mbv1 = bucketTaskDto.getOriMbv();
            MinitorBucketViewDto mbv = new MinitorBucketViewDto();
            //判断之前有没有，有的话，就不查数据库，直接使用已有的数据
            if (mbv1 != null) {
                MinitorBucketViewDto minitorBucketViewDto = JSONObject.parseObject(mbv1, MinitorBucketViewDto.class);
                BeanUtils.copyProperties(minitorBucketViewDto, mbv);
                bucketTaskDto.setMbv(mbv);
                continue;
            }

            //否则去查询，然后去更新
            queryWrapper.in(BucketRecord::getTaskId, bucketTaskDto.getId());
            queryWrapper.eq(BucketRecord::getDelFlag, CommonConstants.DEL_FALSE);
            List<BucketRecord> bucketRecordLists = this.baseMapper.selectList(queryWrapper);


            // 1、计算检索进度
            if (!CollectionUtils.isEmpty(bucketRecordLists)) {
                //计算已经检索的数量
                long count = bucketRecordLists.stream().filter(x -> x.getSearchFlag().equals(CommonConstants.SEARCH_TRUE)).count();
                mbv.setSearchNum(count);
                int size = bucketRecordLists.size();
                mbv.setSearchTotalNum(size);
            }
            // 2、计算图片检索进度
            // 2.1、先计算总的图片数量
            List<BucketRecordDto> newBucketRecordList = bucketRecordLists.stream().map(x -> {
                BucketRecordDto brd = new BucketRecordDto();
                BeanUtils.copyProperties(x, brd);
                return brd;
            }).distinct().collect(Collectors.toList());
            Map<String, String> brMap = newBucketRecordList.stream().collect(Collectors.toMap(BucketRecordDto::getBucket, BucketRecordDto::getTaskId));
            long piatureNum = 0;
            long piatureTotalNum = 0;
            BucketTaskDto bucketTaskDtoFilter = new BucketTaskDto();
            Iterator<Map.Entry<String, String>> iterator = brMap.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, String> entry = iterator.next();
                String key = entry.getKey();
                String value = entry.getValue();
                bucketTaskDtoFilter.setBucketName(key);
                bucketTaskDtoFilter.setTaskId(value);
                MinitorBucketViewDto minitorBucketViewDto = bucketService.searchCountBucketByBucket(bucketTaskDtoFilter);
                piatureNum += minitorBucketViewDto.getPictureNum();
                piatureTotalNum += minitorBucketViewDto.getPictureTotalNum();
            }
            mbv.setPictureNum(piatureNum);
            mbv.setPictureTotalNum(piatureTotalNum);
            bucketTaskDto.setMbv(mbv);
            // 下载图片人物已经完成的，则更新
            updateBucketTaskMbvByTaskId(bucketTaskDto, mbv);
        }
        return list;
    }

    public void updateBucketTaskMbvByTaskId(BucketTaskDto bucketTaskDto, MinitorBucketViewDto mbv) {
        bucketTaskService.updateBucketTaskMbvByTaskId(bucketTaskDto, mbv);
    }


    public Integer countBucketNumByTaskId(String taskId) {
        LambdaQueryWrapper<BucketRecord> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(BucketRecord::getTaskId, taskId);
        queryWrapper.eq(BucketRecord::getSearchFlag, CommonConstants.SEARCH_FALSE);
        queryWrapper.eq(BucketRecord::getDelFlag, CommonConstants.DEL_FALSE);
        Integer integer = this.baseMapper.selectCount(queryWrapper);
        return integer;
    }

    @Override
    public List<BucketRecordDto> SearchBucketDetailsByTaskIds(List<String> ids) {


        LambdaQueryWrapper<BucketRecord> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.in(BucketRecord::getTaskId, ids);
        List<BucketRecord> records = this.baseMapper.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(records)) {
            return Collections.EMPTY_LIST;
        }
        List<BucketRecordDto> newBucketRecordList = records.stream().map(x -> {
            BucketRecordDto brd = new BucketRecordDto();
            BeanUtils.copyProperties(x, brd);
            return brd;
        }).distinct().collect(Collectors.toList());
        return newBucketRecordList;
    }

    @Override
    public void deleteBucketDetailsByTaskIds(List<String> ids) {
        List<BucketRecordDto> bucketRecordDtos = SearchBucketDetailsByTaskIds(ids);
        bucketService.deleteByTaskId(bucketRecordDtos);
    }

    @Override
    public void deleteBucketRecordsByTaskIds(List<String> ids) {
        LambdaQueryWrapper<BucketRecord> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.in(BucketRecord::getTaskId, ids);
        this.baseMapper.delete(queryWrapper);
    }


    /**
     * @Description: 异步处理请求的条件记录，能够及时响应。
     * @Param: * @param beatchNum
     * @return: * @return void
     * @Author: SV00216491
     * @Date: 2024/4/11  10:01
     */


    public void DealSyncBucketRecordDetails(String taskId) {
        System.out.println("初始化线程池完成:{}核心线程为{}-->" + taskExecutor.getThreadNamePrefix());
        log.info("主线程-->" + Thread.currentThread().getName());
        LambdaQueryWrapper<BucketRecord> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(BucketRecord::getTaskId, taskId);
        queryWrapper.eq(BucketRecord::getSearchFlag, CommonConstants.SEARCH_FALSE);
        queryWrapper.eq(BucketRecord::getDelFlag, CommonConstants.DEL_FALSE);
        List<BucketRecord> list = this.baseMapper.selectList(queryWrapper);
        //保存的动作异步处理
        CompletableFuture.runAsync(() -> {
            log.info("子线程-->" + Thread.currentThread().getName());
            String token = httpUtils.obtainApiToken();
            log.info("开始查询token信息" + token);
            log.info("开始根据token异步查询ccd数据{}" + token);
            for (BucketRecord bucketRecord : list) {
                Map<String, Object> queryParams = new HashMap<>();
                //进行日志格式转换，使日期参数统一格式
                DateTime startTime = DateUtil.parse(bucketRecord.getOriginMtimeBegin());
                DateTime endTime = DateUtil.parse(bucketRecord.getOriginMtimeEnd());
                //时区转化
                if (startTime != null && endTime != null) {
                    String originMtimeBegin = DateUtil.format(DateUtil.offsetHour(startTime, -8), "yyyy-MM-dd HH:mm:ss");
                    String originMtimeEnd = DateUtil.format(DateUtil.offsetHour(endTime, -8), "yyyy-MM-dd HH:mm:ss");
                    queryParams.put("originMtimeBegin", originMtimeBegin);
                    queryParams.put("originMtimeEnd", originMtimeEnd);
                }
                queryParams.put("pictureName", bucketRecord.getPictureName());
                queryParams.put("equipmentCode", bucketRecord.getBucket());
                queryParams.put("timeOffset", "1");
                queryParams.put("push", "1");
                log.info("开始根据token异步查询ccd数据 遍历查询参数{}" + JSONObject.toJSONString(queryParams));
                bucketService.PushBucketsBeatch(queryParams, token, taskId);
                //每一个检索之后，需要更新状态
                bucketRecord.setSearchFlag("1");
                this.baseMapper.updateById(bucketRecord);
                log.info("开始根据token异步查询ccd数据成功");
            }
            bucketTaskService.updateOkFlag(taskId);

        }, taskExecutor).whenComplete((res, ex) -> {
                    log.error("当前任务结果" + res);
                    if (ex != null) {
                        log.error("当前任务错误" + ex);
                    }

                }
        );
    }
}
